<?php
/**
 * Установка системы, и модулей который записаны в директории application/modules/
 * Шаги 1-3:
 * 1) Проверка на соотвествие с 
 * 1.1) Версий php и zf
 * 1.2) Проверка настроек php
 * 1.3) Проверка расширений php
 * 2) Создания базы данных
 * 3) Создания админ пароля.
 * 
 * @author nrnwest@gmail.com
 *
 */
class Install_Model_Install
{
 
    /**
     * Названия файла замка инстеляции
     * @var string
     */
    const NAME_FILE_INSTALLLOCK = 'installlock';
    
    /**
     * Вернет масив в котором указны параметры php которые нужно исправить,
     * указав следующие параметры. Если все хорошо вернет true
     * 
     * @return true|array
     */
    public function checkParamsPhpInit()
    {
      $array = array();
      $array['asp_tags'] = 0;
      $array['short_open_tag'] = 1;
      $array['safe_mode'] = 0;
      $array['register_globals'] = 0;
      $array['magic_quotes_gpc'] = 0;
      $array['magic_quotes_runtime'] = 0;
      $array['magic_quotes_sybase'] = 0;
      
      $result = array();
      foreach ($array as $k => $v) {
          $r = (int)ini_get($k);
          if($r === $array[$k]) {
              continue;
          } else {
              $result[$k] = $array[$k];
          }
      }
      if($result === array()) {
          return true;
      }
      return $result;
    }
    
    /**
     * Проверит библиотеки php
     * 
     * @return true|array если нет нужных расширений вернет масив с перечнем нужных расширений.
     */
    public function checkExtensionLoaded()
    {
        $array = array();
        $array[] = 'bz2';
        $array[] = 'curl';
        $array[] = 'gd';
        $array[] = 'imap';
        $array[] = 'mbstring';
        $array[] = 'mcrypt';
        $array[] = 'mhash';
        $array[] = 'mysql';
        $array[] = 'pdo';
        $array[] = 'pdo_mysql';
        $array[] = 'sockets';
        $array[] = 'xmlrpc';
        $array[] = 'xsl';
        $error = array();
        foreach ($array as $v) {
            if(false === extension_loaded($v)) {
              $error[] = $v;  
            }
        }
        
        if($error === array()) {
            return true;
        }
        return $error;
    }
    
    /**
     * Создаем базу данных на основе полученных данных пользователя.
     * @param array $data
     * @return true|sttring если все прошло хорошо вернет true иначе сообщение про ошибку.
     */
    public function createDb($data)
    {
        // пробуем соединиться с полученными данными от пользователя
        $userParamsDb = array();
        $userParamsDb['host']      = $data['host'];
        $userParamsDb['port']      = $data['port'];
        $userParamsDb['adapter']   = $data['adapter'];
        $userParamsDb['username']  = $data['username'];
        $userParamsDb['password']  = $data['password'];
        $userParamsDb['dbname']    = $data['dbname'];
        $userParamsDb['charset']   = $data['charset'];
        // попробуем законектиться под пользователем.
        try {
                $db = Arm_Db::getAdapter($userParamsDb);
                $db->getServerVersion();
            } catch (Exception $e) {
                if(strpos($e->getMessage(), 'Unknown database') === false) {
                return Arm_Translate::_('Ошибка при конекте к базе данных:') . ' ' . $e->getMessage();
            }
        }
    
        $typeServer = Arm_Db::getTypeServer($db);
        // проверяем есть база данных
        try {
                $db->listTables();
            } catch (Exception $e) {
                // базы данных нету пробуем ее создать
                $db->closeConnection();

          // Проверим есть ли рутовский пароль
          if($data['rootuser'] !== '') {
              $user     = $data['rootuser'];
              $password = $data['rootpassword'];
          } else {
              $user     = $data['username'];
              $password = $data['password'];
          } 
          // создаем базу данных. 
          try {
            $db = new PDO($typeServer . ':host='.$data['host'].';port='.$data['port'], $user, $password);
            $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY , true);
          }catch (Exception $e) {
              return  Arm_Translate::_('Ошибка при конекте к серверу: %s' , $e->getMessage());
          }
          /*@var $sql Install_Model_Sql_Pdo_Mysql */
          $sql = Arm_Db::getSqlObject('Install_Model_Sql', Arm_Db::getAdapter());
          try {
            $sql->createDb($userParamsDb['dbname'], $db);
          } catch (Exception $e) {
            return Arm_Translate::_('Ошибка при создании базы данных, попробуйте создать базу в ручном режиме, ошибка: %s',  $e->getMessage());
          }
      }
      
        $db = Arm_Db::getAdapter($userParamsDb); 
        // установка дампа базы данных, удалим все таблици с базы если суещствуют.
        $sql = Arm_Db::getSqlObject('Install_Model_Sql', Arm_Db::getAdapter());
        foreach ($db->listTables() as $table) {
            $sql->dropTable($table);
        }
       
        // выполним damp
        $path = $data['damp'];
        $dump = new Arm_Db_Dump($db);
        $dump->import($path);
        $this->_writeConfigSystem($data, $userParamsDb);
        return true;
    }
    
    /**
     * Запись главного конфигурационого файла.
     * 
     * @param array $data
     * @param array $userParamsDb
     */
    private function _writeConfigSystem($data, $userParamsDb)
    {
        $pathIni = Arm_Core::getPathApplication() . 'configs/application.ini';
        $write = new Arm_Config_Write_Ini($pathIni);
        $dataWrite = array();
        // даные для записи конекта с базой
        foreach ($userParamsDb as $k=>$v) {
            $dataWrite['db.'.$k] = $v;
        }
        // запишем ключ для шифрования данные в системе
        $dataWrite['system.secureKey'] = md5(rand() . microtime(true));
        // путя к php и mysql
        $dataWrite['system.path.php']   = $data['php'];
        $dataWrite['db.dump']           = $data['mysqldump'];
        $dataWrite['db.import']         = $data['mysql'];
      
        // запишем хост системеы
        $dataWrite['system.host'] = Arm_Core::getRequest()->getServer('SERVER_NAME');
        $write->write($dataWrite);
        return;
    }
    
    /**
     * Установка всех модулей в системе.
     */
    public function installModules()
    {
      $modules = Arm_Module::getInstance()->getModulesIsFileSystem();
      foreach ($modules as $module) {
          if($module === 'install') {
              continue;
          }
          $install = new Arm_Module_Install($module);
          $install->install();
      } 
    }
    
    /**
     * Создаст файл robots.txt
     */
    public function createRobotsFile()
    {
        $path = Arm_Core::getPathPublicHtml() . 'robots.txt';
        $fp  = fopen($path, 'wb');
        $str = file_get_contents(Arm_Core::getPathModule('install') . 'models/_file/robots.txt');
        $str = str_replace('{host}', Arm_Core::getConfigApplication()->system->host, $str);
        fwrite($fp, $str); 
        fclose($fp);  
    }
    
    /**
     * Метод создает файл замок против повторной инстеляции.
     */
    public function lock()
    {
       $path = Arm_Core::getPathApplication() . self::NAME_FILE_INSTALLLOCK;
       $fp = fopen($path, 'wb');
       $body = 'System Arm (c)2010,  install date: ' . date("c");
       fwrite($fp, $body);
       fclose($fp);
    }
    
    /**
     * Проверка версии php и Zf
     * если версии ниже требуемых вернет масив с указанием какую версию нужно установить
     */
    public function checkVersion()
    {
        $config = Arm_Module::getInstance()->getConfig('install');
        $error = array();
        if(-1 === version_compare(PHP_VERSION, $config->version->php)) {
            $error['PHP'] = $config->version->php;
        }
        if(-1 === version_compare(Zend_Version::VERSION, $config->version->zf)) {
            $error['Zend Framework'] = $config->version->zf;
        }
        if($error !== array()) {
            return $error;
        }
        return true;
    }
    
    /**
     * Создаст администратора, или обновит его паспорт, если такой пользователь существует.
     * И выполнит вход в систему.
     * 
     * @param array $data
     */
    public function createAdminAcaunt($data, $remidAdmin = 1)
    {
        // ок система установлена выводим сообщение что все в порядке.
        $model = new User_Model_User();
        // проверим есть ли пользователь с данным логином елси обновим паспорт.
        if(true ===  $model->isLogin($data['login'])) {
            $model->updateUser($data, $model->getIdUser($data['login']));
        } else {
            $model->createNewUser($data, Arm_Acl::GROUP_ADMIN); 
        }
        Arm_User::getInstance()->login($data['login'], $data['password'], $remidAdmin);
        return;
    }

}